package com.cmas.platform.service.impl;

import java.util.List;

import com.aidex.common.annotation.DataSource;
import com.aidex.common.constant.Constants;
import com.aidex.common.core.domain.model.LoginUser;
import com.aidex.common.enums.DataSourceType;
import com.aidex.common.exception.CustomException;
import com.aidex.common.utils.SecurityUtils;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmas.platform.domain.NotificationUser;
import com.cmas.platform.domain.Region;
import com.cmas.platform.domain.UserRecord;
import com.cmas.platform.domain.em.ApproveStatusEnum;
import com.cmas.platform.domain.em.MessageTypeEnum;
import com.cmas.platform.domain.em.NotificationTypeEnum;
import com.cmas.platform.domain.em.SystemNotificationTypeEnum;
import com.cmas.platform.mapper.NotificationUserMapper;
import com.cmas.platform.mapper.RegionMapper;
import com.cmas.platform.mapper.UserRecordMapper;
import com.cmas.platform.service.RegionService;
import com.cmas.platform.service.UserRecordService;
import com.cmas.platform.utils.PushNoticeUtils;
import com.cmas.platform.vo.LastNotificationVo;
import com.cmas.platform.vo.NotificationVo;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aidex.common.core.domain.BaseEntity;
import com.aidex.common.utils.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cmas.platform.mapper.NotificationMapper;
import com.cmas.platform.domain.Notification;
import com.cmas.platform.service.NotificationService;
import org.springframework.transaction.annotation.Transactional;


/**
 * 推送表Service业务层处理
 *
 * @author su
 * @email 1218819874@qq.com
 * @date 2024-05-14
 */
@Service
public class NotificationServiceImpl extends ServiceImpl<NotificationMapper, Notification> implements NotificationService {

    private static final Logger log = LoggerFactory.getLogger(NotificationServiceImpl.class);


    @Autowired
    private RegionMapper regionMapper;

    @Autowired
    private UserRecordMapper userRecordMapper;

    @Autowired
    private NotificationUserMapper notificationUserMapper;


    /**
     * 查询推送表列表
     *
     * @param notification 推送表
     * @return 推送表
     */
    @Override
    public List<Notification> selectNotificationList(Notification notification) {
        return baseMapper.selectList(setQueryWrapper(notification));
    }

    public QueryWrapper<Notification> setQueryWrapper(Notification notification) {
        QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(notification.getItemId())) {
            queryWrapper.eq("cmas.notification.item_id", notification.getItemId());
        }
        if (StringUtils.isNotEmpty(notification.getUserId())) {
            queryWrapper.eq("cmas.notification.user_id", notification.getUserId());
        }
        if (StringUtils.isNotEmpty(notification.getRegionId())) {
            queryWrapper.eq("cmas.notification.region_id", notification.getRegionId());
        }
        if (StringUtils.isNotEmpty(notification.getType())) {
            queryWrapper.eq("cmas.notification.type", notification.getType());
        }
        if (StringUtils.isNotEmpty(notification.getTitle())) {
            queryWrapper.like("cmas.notification.title", notification.getTitle());
        }
        if (StringUtils.isNotEmpty(notification.getContent())) {
            queryWrapper.like("cmas.notification.content", notification.getContent());
        }
        return queryWrapper;
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = Constants.NOTICE_QUEUE, durable = "true"),
            exchange = @Exchange(name = Constants.NOTICE_EXCHANGE, type = ExchangeTypes.TOPIC),
            key = Constants.NOTICE_QUEUE_ROUTING_KEY))
    @DataSource(value = DataSourceType.SLAVE)
    public void pushNotificationByRabbitmq(String msg) {
        try {
            JSONObject message = JSONObject.parse(msg);
            Notification notification = setNotification(message);
            // 0:选择地区 1:地区消息
            switch (message.getString("type")) {
                case ("0"):
                    pushSystem(message, notification);
                    break;
                case ("1"):
                    pushRegionPost(notification);
                    break;
            }

        } catch (Exception e) {
            throw new CustomException("消息接受失败!");
        }
    }

    private void pushRegionPost(Notification notification) {
        notification.setType(NotificationTypeEnum.REGION.getValue());
        if (StringUtils.isEmpty(notification.getId())) {
            baseMapper.insert(notification);
        }
        PushNoticeUtils.pushRegionNotification(baseMapper
                .selectRegionNotification(notification.getId()));
    }

    /**
     * 推送系统消息
     *
     * @param message
     * @param notification
     */
    private void pushSystem(JSONObject message, Notification notification) {
        if (message.get("systemType").equals(SystemNotificationTypeEnum
                .CHOOSE_REGION.getValue())) {
            pushChooseRegion(notification);
        } else if (message.get("systemType").equals(SystemNotificationTypeEnum
                .OPERATOR_APPLY.getValue())) {
            pushOperatorApply(message, notification);
        }
    }

    private void pushOperatorApply(JSONObject message, Notification notification) {
        notification.setType(NotificationTypeEnum.SYSTEM.getValue());
        notification.setTitle("系统消息");
        if (message.get("status").equals(ApproveStatusEnum
                .ARTIFICIAL_PASS.getValue())) {
            notification.setContent("恭喜申请成为运营者成功，请到管理系统设置地区");
        } else {
            notification.setContent("申请成为运营者未通过，请30天后重新申请");
        }
        notification.setRegionId(null);
        if (StringUtils.isEmpty(notification.getId())) {
            baseMapper.insert(notification);
        }
        PushNoticeUtils.pushUserNotification(notification);
    }


    private void pushChooseRegion(Notification notification) {
        notification.setType(NotificationTypeEnum.SYSTEM.getValue());
        Region region = regionMapper.selectById(notification.getRegionId());
        notification.setTitle("系统消息");
        notification.setContent("选择地区【" + region.getName() + "】成功");
        notification.setRegionId(null);
        if (StringUtils.isEmpty(notification.getId())) {
            baseMapper.insert(notification);
        }
        PushNoticeUtils.pushUserNotification(notification);
    }

    private Notification setNotification(JSONObject message) {
        Notification notification = new Notification();
        if (StringUtils.isNotEmpty(message.getString("userId"))) {
            notification.setUserId(message.getString("userId"));
        }
        if (StringUtils.isNotEmpty(message.getString("regionId"))) {
            notification.setRegionId(message.getString("regionId"));
        }
        if (StringUtils.isNotEmpty(message.getString("itemId"))) {
            notification.setItemId(message.getString("itemId"));
        }
        if (StringUtils.isNotEmpty(message.getString("content"))) {
            notification.setContent(message.getString("content"));
        }
        return notification;
    }


    /**
     * 批量删除推送表
     *
     * @param ids 需要删除的推送表ID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteNotificationByIds(String[] ids) {
        notificationUserMapper.delete(new QueryWrapper<NotificationUser>()
                .lambda().in(NotificationUser::getNotificationId, ids));
        return baseMapper.deleteNotificationByIds(ids, BaseEntity.DEL_FLAG_DELETE);
    }

    @Override
    public List<NotificationVo> selectNotificationVoList(Notification notification) {
        return baseMapper.selectNotificationVoList(setQueryWrapper(notification));
    }

    @Override
    public IPage<LastNotificationVo> selectLastNotificationVoList(Integer current, Integer size, Notification notification) {
        Page<LastNotificationVo> page = new Page<>(current, size);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        judgeRegion(notification);
        page.setRecords(baseMapper.selectLastNotification(current, size,
                loginUser.getUserId(), notification.getRegionId()));
        return page;
    }

    @Override
    public Notification addNotification(Notification notification) {
        baseMapper.insert(notification);
        // 选择地区,地区消息
        if (notification.getType()
                .equals(NotificationTypeEnum.SYSTEM.getValue())) {
            pushChooseRegion(notification);
        } else if (notification.getType()
                .equals(NotificationTypeEnum.REGION.getValue())) {
            pushRegionPost(notification);
        }
        return notification;
    }

    @Override
    public int unReadNotificationCount(Notification notification) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        judgeRegion(notification);
        return baseMapper.unReadNotificationCount(loginUser.getUserId(), notification.getRegionId());
    }

    @Override
    public List<NotificationVo> selectNotificationDetailList(Notification notification) {
        if (notification.getType().equals(NotificationTypeEnum.REGION.getValue())) {
            judgeRegion(notification);
        }
        return baseMapper.selectNotificationVoList(setQueryWrapper(notification));
    }


    private void judgeRegion(Notification notification) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (StringUtils.isEmpty(notification.getRegionId())) {
            UserRecord userRecord = userRecordMapper.selectOne(new QueryWrapper<UserRecord>()
                    .lambda().eq(UserRecord::getUserId, loginUser.getUserId()));
            if (userRecord != null) {
                notification.setRegionId(userRecord.getRegionId());
            }
        }
    }


}
